﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ScrumTime.ViewModels;
using ScrumTime.Services;
using ScrumTime.Models;
using ScrumTime.Helpers;


namespace ScrumTime.Controllers
{
    public class UserController : Controller
    {
        ScrumTimeEntities _ScrumTimeEntities;
        UserService _UserService;


        #region metodos privados auxiliares

        private System.Web.Security.MembershipUser getUser( String username, AccountMembershipService accountService ){
            System.Web.Security.MembershipUser resultado = null;
            foreach (System.Web.Security.MembershipUser user in accountService.GetAllUsers() ) {
                if (username == user.UserName) {
                    resultado = user;
                    break;
                }
            }
            return resultado;
        }

        #endregion


        public UserController()
        {
            _ScrumTimeEntities = new ScrumTimeEntities();
            _UserService = new UserService(_ScrumTimeEntities);            
        }

        

        [Authorize]
        public ActionResult Index()
        {
            int ProductId;
            
            ProductId = Helpers.SessionHelper.GetCurrentProductId(Session);


            UserViewModel userviewmodel = 
                new UserViewModel(ProductId, 
                    ScrumTime.Helpers.SessionHelper.GetIsUserAdmin(),
                    ScrumTime.Helpers.ScrumTimePrivilege.canEditUser(Session)
                    );

            return View(userviewmodel);
        }

        [Authorize]
        public ActionResult Delete( String username)
        {
            try
            {

                ScrumTimeEntities scrumTimeEntities = new ScrumTimeEntities();

                String user_gui = _UserService.GetGuiByName(username);
                ScrumTime.Models.User user = UserService.GetUserByGUID(scrumTimeEntities, user_gui);
                

                if (User.Identity.Name == username) {
                    throw new Exception("Can not delete this user.");
                }

                if (user.Tasks.Count > 0)
                    throw new Exception("The user has assigned tasks.");

                if (user.ScrumDetails.Count > 0)
                    throw new Exception("The user has registered tasks.");


                //ahora, si el usuario no tiene registrada ninguna tarea para el, verificamos que no 
                // si esta asociado a algun otro producto
                if (_UserService.userAssociatedWithAnotherProduct(user_gui))
                {
                    int productId = SessionHelper.GetCurrentProductId(User.Identity.Name, Session);
                    _UserService.removeUserFromThisProduct(user_gui, productId);
                }
                else {
                    // eliminamos la asociacion que existe entre el producto y el usuario
                    _UserService.removeUserFromAllProduct(user_gui);
                    // si no tiene asociado nada, eliminamos y ya
                    AccountMembershipService membershipService = new AccountMembershipService();
                    membershipService.DeleteUser(username);

                    scrumTimeEntities.DeleteObject(user);
                    scrumTimeEntities.SaveChanges();

                }

                    
                

                return Redirect("index");
            }
            catch (Exception e)
            {
                return Redirect(ErrorHelper.GetURLGeneralError(e.Message));  
            }
            
        }


        private String getUserId(String name, AccountMembershipService membershipService) {
            String resultado = name;
            name = name.ToString();
            System.Web.Security.MembershipUserCollection userCollection = membershipService.GetAllUsers();

            foreach (System.Web.Security.MembershipUser user in userCollection) {
                if (user.UserName == name) {                    
                    resultado = user.ProviderUserKey.ToString();
                    break;
                }
            }
            return resultado;
        }

        private ScrumTime.Models.Role GetRol(int rolId ) {
            ScrumTime.Models.Role resultado = null;
            foreach( Role r in _ScrumTimeEntities.Roles){
                if ( r.RolId == rolId){
                    resultado = r;
                    break;
                }
            }
            return resultado;
        }

        [Authorize]
        public ActionResult edit(FormCollection collection)
        {
            try
            {
                string newuser = collection.Get("newuser");
                string name = collection.Get("name");
                string mail = collection.Get("mail");
                string password = collection.Get("password");

                int rolId = ScrumTimeAppConfig.GetUserId_Developer();

                if (collection.Get("rolId") != null) { 
                    rolId= int.Parse(collection.Get("rolId") );
                }


                ProductService productService = new ProductService(_ScrumTimeEntities);
                int productId = SessionHelper.GetCurrentProductId(User.Identity.Name, Session);                
                if (productId == -1)
                {
                    throw new Exception("No product selected.");
                }
                Product product = productService.GetProductById(productId);

                AccountMembershipService membershipService = new AccountMembershipService();

                if (newuser.ToLower() == "true")
                {
                    System.Web.Security.MembershipCreateStatus mcs = membershipService.CreateUser(name, password, mail);
                    if (mcs != System.Web.Security.MembershipCreateStatus.Success)
                    {
                        throw new Exception(mcs.ToString());
                    }
                    //creamos el usuario
                    ScrumTime.Models.User new_user = new ScrumTime.Models.User();

                    String userId = getUserId(name, membershipService);
                    new_user.UserId = new Guid( userId);
                    new_user.UserName = name;
                    new_user.Roles.Add(GetRol(rolId));

                    try
                    {
                        _ScrumTimeEntities.AddToUsers(new_user);
                        _ScrumTimeEntities.SaveChanges();
                    }
                    catch (Exception e) {
                        membershipService.DeleteUser(name);
                        throw e;
                    }
                    
                    product.Users.Add(new_user);

                    _ScrumTimeEntities.ObjectStateManager.ChangeObjectState(product, System.Data.EntityState.Modified);
                    _ScrumTimeEntities.SaveChanges();

                }
                else {
                    System.Web.Security.MembershipUser user = getUser(name, membershipService);

                    ScrumTime.Services.UserService userService = new ScrumTime.Services.UserService(_ScrumTimeEntities);
                    User u = userService.GetUserByGuid(user.ProviderUserKey.ToString());
                    user.Email = mail;                    
                    u.Roles.Clear();
                    u.Roles.Add(GetRol(rolId));
                    System.Web.Security.Membership.UpdateUser(user);

                    _ScrumTimeEntities.ObjectStateManager.ChangeObjectState(u, System.Data.EntityState.Modified);
                    _ScrumTimeEntities.SaveChanges();
                }

                return Redirect("index");
            }
            catch(Exception e )
            {
                return Redirect(ErrorHelper.GetURLGeneralError(e.Message));
            }

        }


        [Authorize]
        public ActionResult addExistUser(FormCollection collection)
        {
            try
            {
                string gui = collection.Get("gui");
                if (gui.Length > 0) {

                    int productId = SessionHelper.GetCurrentProductId(User.Identity.Name, Session);
                    if (productId == -1)
                    {
                        throw new Exception("No product selected.");
                    }
                    ScrumTime.Services.UserService userService = new ScrumTime.Services.UserService(this._ScrumTimeEntities);
                    ScrumTime.Models.User user = userService.GetUserByGUI(gui);
                    ProductService productService = new ProductService(_ScrumTimeEntities);
                    Product product = productService.GetProductById(productId);
                    product.Users.Add(user);
                    _ScrumTimeEntities.ObjectStateManager.ChangeObjectState(product, System.Data.EntityState.Modified);

                    _ScrumTimeEntities.SaveChanges();
                }


                return Redirect("index");
            }
            catch (Exception e)
            {
                return Redirect(ErrorHelper.GetURLGeneralError(e.Message));
            }

        }


        [Authorize]
        public ActionResult resetPassword(FormCollection collection)
        {
            try
            {
                string name = collection.Get("name");
                AccountMembershipService membershipService = new AccountMembershipService();
                System.Web.Security.MembershipUser user = getUser(name, membershipService);
                String password_reset =  user.ResetPassword();
                user.ChangePassword(password_reset, "password");
                return Redirect("index");
            }
            catch (Exception e)
            {
                return Redirect(ErrorHelper.GetURLGeneralError(e.Message));
            }

        }


        [Authorize]
        public ActionResult data(FormCollection collection)
        {
            try
            {
                // en este caso el gui, es el nombre
                string gui = collection.Get("gui"); 
               
                AccountMembershipService membershipService = new AccountMembershipService();
                System.Web.Security.MembershipUser user =  this.getUser(gui, membershipService);

                ScrumTime.Services.UserService userService =
                     new ScrumTime.Services.UserService();
                ;

                ScrumTime.Models.UserInfo userInfo = 
                    new ScrumTime.Models.UserInfo(
                        userService.GetUserByGuid(user.ProviderUserKey.ToString()),
                        user);

                
                return PartialView("data", userInfo);
            }
            catch (Exception e)
            {
                return Redirect(ErrorHelper.GetURLGeneralError(e.Message));
            }

        }
    
    }
}
